﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using AEM.Utils;
using AEM.Data;
using System.Globalization;


namespace AEM.Common
{
    public static class DataLogHelper
    {
        static string logPath = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "datalogs");

        /// <summary>
        /// 获取数据最早发生时间
        /// </summary>
        /// <returns></returns>
        public static DateTime GetEarliestTime()
        {
            if (!Directory.Exists(logPath)) Directory.CreateDirectory(logPath);
            DirectoryInfo d = new DirectoryInfo(logPath);
            DateTime s = DateTime.Now;
            if (null != d)
            {
                DirectoryInfo[] arr = d.GetDirectories("*", SearchOption.TopDirectoryOnly);
                foreach (var i in arr)
                {
                    if ((s - i.Name.toDateTime()).Seconds > 0)
                        s = new DateTime(i.Name.Substring(0, 4).toInt32(), i.Name.Substring(4, 2).toInt32(), i.Name.Substring(6, 2).toInt32());
                }
            }
            return s;
        }

        /// <summary>
        /// 获取电梯故障状态记录表信息
        /// </summary>
        /// <param name="s">开始时间</param>
        /// <param name="t">结束时间</param>
        /// <returns></returns>
        public static List<Data.DataLog.TableFaultLogRow> GetFaultLog(DateTime s, DateTime t)
        {
            return GetFaultLog(null, s, t);
        }

        /// <summary>
        /// 获取电梯故障状态记录表信息
        /// </summary>
        /// <param name="r">指定的电梯信息</param>
        /// <param name="s">开始时间</param>
        /// <param name="t">结束时间</param>
        /// <returns></returns>
        public static List<Data.DataLog.TableFaultLogRow> GetFaultLog(Data.Model.LiftInfo lift, DateTime s, DateTime t)
        {
            List<Data.DataLog.TableFaultLogRow> list = new List<DataLog.TableFaultLogRow>();
            List<string> flist = new List<string>();
            flist = GetFaultFile(lift, s, t);
            foreach (string f in flist)
            {
                Data.DataLog logdb = new Data.DataLog(f);
                if (null != logdb)
                    list.AddRange(logdb.TableFaultLog.Rows.OfType<Data.DataLog.TableFaultLogRow>());
            }
            return list;
        }

        /// <summary>
        /// 获取数据文件列表
        /// </summary>
        /// <param name="lift"></param>
        /// <param name="s"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        private static List<string> GetFaultFile(Data.Model.LiftInfo lift, DateTime s, DateTime t)
        {
            List<string> flist = new List<string>();
            for (int i = 0; i <= (t - s).Days; i++)
            {
                string path = Path.Combine(logPath, s.AddDays(i).ToString("yyyyMMdd"));
                if (null != lift)
                {
                    string filename = Path.Combine(path, lift.LiftNum + ".xml");
                    if (File.Exists(filename))
                        flist.Add(filename);
                }
                else
                {
                    if (Directory.Exists(path))
                    {
                        DirectoryInfo dir = new DirectoryInfo(path);
                        if (null != dir)
                        {
                            foreach (FileInfo f in dir.GetFiles("*.xml"))
                            {
                                flist.Add(f.FullName);
                            }
                        }
                    }
                }
            }
            return flist;
        }

        /// <summary>
        /// 获取电梯外召记录表信息
        /// </summary>
        /// <param name="lift">指定的电梯信息</param>
        /// <param name="s"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static List<DataLog.TableHallCallLogRow> GetHallCallLog(Data.Model.LiftInfo lift, DateTime s, DateTime t)
        {
            List<Data.DataLog.TableHallCallLogRow> list = new List<DataLog.TableHallCallLogRow>();
            List<string> flist = new List<string>();
            flist = GetFaultFile(lift, s, t);
            foreach (string f in flist)
            {
                Data.DataLog logdb = new Data.DataLog(f);
                if (null != logdb)
                    list.AddRange(logdb.TableHallCallLog.Rows.OfType<Data.DataLog.TableHallCallLogRow>());
            }
            return list;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="r">电梯</param>
        /// <param name="s">开始时间</param>
        /// <param name="t">结束时间</param>
        /// <param name="d">上下行</param>
        /// <param name="l">层站</param>
        /// <returns></returns>
        public static int GetHallCallCount(Data.Model.LiftInfo lift, DateTime s, DateTime t, int d, int l)
        {
            List<DataLog.TableHallCallLogRow> hclist = GetHallCallLog(lift, s, t);
            if (null != hclist)
            {
                int count = 0;
                if (-1 != l)
                {
                    if (-1 != d)
                    {
                        count = (from DataLog.TableHallCallLogRow r in hclist
                                 where r.CallType == d && r.Floor == l
                                 select r).Count();
                    }
                    else
                    {
                        count = (from DataLog.TableHallCallLogRow r in hclist
                                 where r.Floor == l
                                 select r).Count();
                    }
                }
                else
                {
                    if (-1 != d)
                    {
                        count = (from DataLog.TableHallCallLogRow r in hclist
                                 where r.CallType == d
                                 select r).Count();
                    }
                    else
                    {
                        count = (from DataLog.TableHallCallLogRow r in hclist
                                 select r).Count();
                    }
                }
                return count;
            }
            return 0;
        }

        public static int[] GetHallCallCount(Data.Model.LiftInfo lift, DateTime s, DateTime t, int d)
        {
            List<DataLog.TableHallCallLogRow> hclist = GetHallCallLog(lift, s, t);
            if (null != hclist)
            {
                int len = lift.LiftActualFloor.Split(',').Length;
                int[] nc = new int[len];
                if (-1 != d)
                {
                    for (int i = 1; i <= len; i++)
                    {
                        int count = 0;
                        count = (from DataLog.TableHallCallLogRow r in hclist
                                 where r.CallType == d && r.Floor == i
                                 select r).Count();
                        nc[i - 1] = count;
                    }
                }
                else
                {
                    for (int i = 1; i <= len; i++)
                    {
                        int count = 0;
                        count = (from DataLog.TableHallCallLogRow r in hclist
                                 where r.Floor == i
                                 select r).Count();
                        nc[i - 1] = count;
                    }
                }
                return nc;
            }
            return null;
        }

        public static double GetStatusCount(Data.Model.LiftInfo l, DateTime s, DateTime t, out double os, out double oh, out double nc, out double nl)
        {
            os = 0; oh = 0; nc = 0; nl = 0;
            DateTime tmp = DateTime.Now;

            List<Data.DataLog.TableFaultLogRow> flist = GetFaultLog(l, s, t);

            if (null != flist)
            {
                os = (from DataLog.TableFaultLogRow r in flist
                      where r.FT == (int)Data.Enum.LiftStatus.OutOfService
                      select (r.ET - r.ST).TotalMilliseconds).Sum();
                oh = (from DataLog.TableFaultLogRow r in flist
                      where r.FT == (int)Data.Enum.LiftStatus.Overhaul
                      select (r.ET - r.ST).TotalMilliseconds).Sum();
                nc = (from DataLog.TableFaultLogRow r in flist
                      where r.FT == (int)Data.Enum.LiftStatus.NC
                      select (r.ET - r.ST).TotalMilliseconds).Sum();

                nl = (from DataLog.TableFaultLogRow r in flist
                      where r.FT == (int)Data.Enum.LiftStatus.Normal
                      select (r.ET - r.ST).TotalMilliseconds).Sum();
            }
            return 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="r">电梯</param>
        /// <param name="s">开始时间</param>
        /// <param name="t">结束时间</param>
        /// <param name="d">上下行</param>
        /// <param name="l">层站</param>
        /// <param name="max"></param>
        /// <param name="min"></param>
        /// <param name="avg"></param>
        /// <returns></returns>
        public static double GetWaitingTime(Data.Model.LiftInfo lift, DateTime s, DateTime t, int d, int l, out double max, out double min, out double avg)
        {
            max = 0; min = double.MaxValue; avg = 0;
            List<DataLog.TableHallCallLogRow> hclist = GetHallCallLog(lift, s, t);
            if (null != hclist)
            {
                if (-1 != l)
                {
                    if (-1 != d)
                    {
                        max = (from DataLog.TableHallCallLogRow r in hclist
                               where r.Floor == l && r.CallType == d
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Max();
                        avg = (from DataLog.TableHallCallLogRow r in hclist
                               where r.Floor == l && r.CallType == d
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Average();
                        min = (from DataLog.TableHallCallLogRow r in hclist
                               where r.Floor == l && r.CallType == d && r.EndTime != r.StartTime
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Min();
                    }
                    else
                    {
                        max = (from DataLog.TableHallCallLogRow r in hclist
                               where r.Floor == l
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Max();
                        avg = (from DataLog.TableHallCallLogRow r in hclist
                               where r.Floor == l
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Average();
                        min = (from DataLog.TableHallCallLogRow r in hclist
                               where r.Floor == l && r.EndTime != r.StartTime
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Min();
                    }
                }
                else
                {
                    if (-1 != d)
                    {
                        max = (from DataLog.TableHallCallLogRow r in hclist
                               where r.CallType == d
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Max();
                        avg = (from DataLog.TableHallCallLogRow r in hclist
                               where r.CallType == d
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Average();
                        min = (from DataLog.TableHallCallLogRow r in hclist
                               where r.CallType == d && r.EndTime != r.StartTime
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Min();
                    }
                    else
                    {
                        max = (from DataLog.TableHallCallLogRow r in hclist
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Max();
                        avg = (from DataLog.TableHallCallLogRow r in hclist
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Average();
                        min = (from DataLog.TableHallCallLogRow r in hclist
                               where r.EndTime != r.StartTime
                               select (r.EndTime - r.StartTime).TotalMilliseconds).Min();
                    }
                }
            }
            return 0;
        }

        public static int GetUpDownCount(Data.Model.LiftInfo lift, DateTime s, DateTime t, int l, out int up, out int down)
        {
            up = 0; down = 0;
            List<DataLog.TableHallCallLogRow> hclist = GetHallCallLog(lift, s, t);
            if (null != hclist)
            {
                if (-1 != l)
                {
                    up = (from DataLog.TableHallCallLogRow r in hclist
                          where r.CallType == (int)Data.Enum.CallType.Up && r.Floor == l
                          select r).Count();
                    down = (from DataLog.TableHallCallLogRow r in hclist
                            where r.CallType == (int)Data.Enum.CallType.Down && r.Floor == l
                            select r).Count();
                }
                else
                {
                    up = (from DataLog.TableHallCallLogRow r in hclist
                          where r.CallType == (int)Data.Enum.CallType.Up
                          select r).Count();
                    down = (from DataLog.TableHallCallLogRow r in hclist
                            where r.CallType == (int)Data.Enum.CallType.Down
                            select r).Count();
                }
            }
            return 0;
        }

        public static void GetRunTime(Data.Model.LiftInfo liftInfo, DateTime s, DateTime t, out string time, out string times, out string doors)
        {
            List<DataLog.TableRunTimeRow> rtlist = GetRunTimeLog(liftInfo, s, t, out times, out doors);
            double dd = (from DataLog.TableRunTimeRow r in rtlist
                         select (r.ET - r.ST).Days).Sum();
            double hh = (from DataLog.TableRunTimeRow r in rtlist
                         select (r.ET - r.ST).Hours).Sum();
            double mm = (from DataLog.TableRunTimeRow r in rtlist
                         select (r.ET - r.ST).Minutes).Sum();
            double ss = (from DataLog.TableRunTimeRow r in rtlist
                         select (r.ET - r.ST).Seconds).Sum();
            time = (new TimeSpan(dd.toInt32(), hh.toInt32(), mm.toInt32(), ss.toInt32())).ToString("g");

        }

        private static List<DataLog.TableRunTimeRow> GetRunTimeLog(Data.Model.LiftInfo liftInfo, DateTime s, DateTime t, out string times, out string doors)
        {
            double _times = 0, _doors = 0;
            List<Data.DataLog.TableRunTimeRow> list = new List<DataLog.TableRunTimeRow>();
            List<string> flist = new List<string>();
            flist = GetFaultFile(liftInfo, s, t);
            foreach (string f in flist)
            {
                Data.DataLog logdb = new Data.DataLog(f);
                if (null != logdb)
                {
                    list.AddRange(logdb.TableRunTime.Rows.OfType<Data.DataLog.TableRunTimeRow>());
                    _times += Convert.ToDouble(logdb.TableCount.Rows[0][1]);
                    _doors += Convert.ToDouble(logdb.TableCount.Rows[0][2]);
                }
            }
            times = _times.ToString();
            doors = _doors.ToString();
            return list;
        }


        ///////////////////////////////////////////////////////////

        public static List<SerialDataEventArgs> GetSerialDataLog(Data.Model.LiftInfo lift, DateTime s, DateTime t)
        {
            List<FileInfo> flist = new List<FileInfo>();
            flist = GetFileList(lift, s, t);
            List<SerialDataEventArgs> slist = GetSerialDataLog(flist);
            return slist;
        }

        private static List<SerialDataEventArgs> GetSerialDataLog(List<FileInfo> flist)
        {
            List<SerialDataEventArgs> slist = new List<SerialDataEventArgs>();
            foreach (FileInfo f in flist)
            {
                if (null != f)
                    slist.AddRange(GetSerialDataLog(f));
            }
            return slist;
        }

        private static IEnumerable<SerialDataEventArgs> GetSerialDataLog(FileInfo f)
        {
            List<SerialDataEventArgs> slist = new List<SerialDataEventArgs>();
            if (null != f)
            {
                BinaryReader binReader = new BinaryReader(f.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
                try
                {
                    long count = (int)f.Length;
                    byte[] buffer = new byte[count];
                    binReader.Read(buffer, 0, buffer.Length);
                    string fileinfo = Encoding.Default.GetString(buffer);
                    string[] arr = fileinfo.Split('|');
                    foreach (string s in arr)
                    {
                        try
                        {
                           /* string[] item = s.Split('=');
                            DateTime d = item[0].Replace(' ', '.').toDateTime();
                            SerialDataEventArgs args = new SerialDataEventArgs(item[1].toByteArray(NumberStyles.HexNumber).ToList());
                            args.TimeRecieved = d;
                            slist.Add(args);*/
                        }
                        catch { continue; }
                    }
                }
                catch { }
                finally
                {
                    binReader.Close();
                }

            }
            return slist;
        }

        private static List<FileInfo> GetFileList(Data.Model.LiftInfo lift, DateTime s, DateTime t)
        {
            List<FileInfo> flist = new List<FileInfo>();
            for (int i = 0; i <= (t - s).Days; i++)
            {
                string path = Path.Combine(logPath, s.AddDays(i).ToString("yyyyMMdd"));
                if (null != lift)
                {
                    string filename = Path.Combine(path, lift.LiftNum + ".dll");
                    if (File.Exists(filename))
                        flist.Add(new FileInfo(filename));
                }
                else
                {
                    if (Directory.Exists(path))
                    {
                        DirectoryInfo dir = new DirectoryInfo(path);
                        if (null != dir)
                            flist.AddRange(dir.GetFiles());
                    }
                }
            }
            return flist;
        }


    }
}
